package com.topnav.mc.admin.security.jwt.handle;

import com.topnav.mc.admin.security.config.JwtProperties;
import com.topnav.mc.admin.security.jwt.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 说明： 自定义的Token过滤器
 * @类名: Role
 * <p>
 *
 * </p>
 * @author   kenny
 * @Date	 2022年2月9日下午5:26:18
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private JwtProperties jwtProperties;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        /** 如果在前端测试时出现跨域问题，到收藏的博客里面看一看 */
        //log.debug("进入自定义过滤器");
        String requestUrl = httpServletRequest.getRequestURI();
        String authToken = httpServletRequest.getHeader(jwtProperties.getHeader());
        if (StringUtils.isEmpty(authToken)){
            authToken = httpServletRequest.getParameter(jwtProperties.getHeader());
        }

        String userName = jwtTokenUtil.getUsernameFromToken(authToken);

        //log.debug("进入自定义过滤器，用户名 [{}]",userName);

        /** 当token中的username不为空时进行验证token是否是有效的token */
        if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            /** token中username不为空，并且Context中的认证为空，进行token验证,从数据库得到带有密码的完整user信息 */
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(userName);
            if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                /**
                 * UsernamePasswordAuthenticationToken继承AbstractAuthenticationToken实现Authentication
                 * 所以当在页面中输入用户名和密码之后首先会进入到UsernamePasswordAuthenticationToken验证(Authentication)，
                 * 然后生成的Authentication会被交由AuthenticationManager来进行管理
                 * 而AuthenticationManager管理一系列的AuthenticationProvider，
                 * 而每一个Provider都会通UserDetailsService和UserDetail来返回一个
                 * 以UsernamePasswordAuthenticationToken实现的带用户名和密码以及权限的Authentication
                 */
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));

                /**
                 * 重点
                 * 将authentication放入SecurityContextHolder中 */
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

/*    private void response(HttpServletResponse response,ExceptionMsg em) throws IOException{
    	String json = JSON.toJSONString(ResultUtil.result(em));

        // 允许跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        // 允许自定义请求头token(允许head跨域)
        response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");

        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(json);

    }*/
}
